package com.rayo.accesscontrollercopy.module.setting;

import android.animation.ObjectAnimator;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.github.johnkil.print.PrintView;
import com.github.ybq.android.spinkit.SpinKitView;
import com.github.ybq.android.spinkit.style.Wave;
import com.litesuits.common.utils.HexUtil;
import com.rayo.accesscontrollercopy.R;
import com.rayo.accesscontrollercopy.config.GlobalVariables;
import com.rayo.accesscontrollercopy.model.db.bean.KeyData;
import com.rayo.accesscontrollercopy.model.db.bean.SiteData;
import com.rayo.accesscontrollercopy.model.db.dao.KeyDataDao;
import com.rayo.accesscontrollercopy.model.db.dao.KeyDataImp;
import com.rayo.accesscontrollercopy.model.db.dao.SiteDao;
import com.rayo.accesscontrollercopy.model.db.dao.SiteImpl;
import com.rayo.accesscontrollercopy.module.adapter.OnClicker;
import com.rayo.accesscontrollercopy.module.adapter.SetKeyAdapter;
import com.rayo.accesscontrollercopy.utils.AppUtils;
import com.rayo.accesscontrollercopy.utils.BroadcastUtils;
import com.rayo.accesscontrollercopy.utils.CancelUtils;
import com.rayo.accesscontrollercopy.utils.TimeFormatUtil;
import com.rayo.accesscontrollercopy.utils.ToastUtils;
import com.rayo.keyholder.data.KeyHolderCmd;
import com.rayo.keyholder.data.KeyHolderData;
import com.rayo.keyholder.serialport.KeyHolderService;
import com.rayo.wallreader.data.KeyBasicInfo;
import com.rayo.wallreader.data.KeyType;
import com.rayo.wallreader.data.UserKeyInfo;
import com.rayo.wallreader.jni.WallreaderJni;
import com.rayo.wallreader.serialport.OnPortListener;
import com.rayo.wallreader.serialport.PortClass;
import com.rayo.wallreader.serialport.ReaderPort;
import com.rayo.wallreader.serialport.ReaderPortThread;
import com.rayo.wallreader.utils.TimeUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

import static com.rayo.accesscontrollercopy.module.main.MainActivity.DOOR_CLOSE;
import static com.rayo.accesscontrollercopy.module.main.MainActivity.DOOR_OPEN;
import static com.rayo.accesscontrollercopy.module.main.MainActivity.START;
import static com.rayo.accesscontrollercopy.module.main.MainActivity.STOP;
import static com.rayo.accesscontrollercopy.module.main.MainActivity.mStatus;
import static com.rayo.accesscontrollercopy.utils.TimeFormatUtil.inttoTwoBytes;

/**
 * Created by lyc-pc on 17/3/14.
 */

public class SetKeyActivity extends AppCompatActivity {
    @BindView(R.id.btn_activity_setkey_bind)
    Button mBtnActivitySetkeyBind;
    @BindView(R.id.btn_activity_setkey_finish)
    Button mBtnActivitySetkeyFinish;
    @BindView(R.id.rlv_activity_setkey)
    RecyclerView mRlvActivitySetkey;
    @BindView(R.id.sv_activity_setkey_loading)
    SpinKitView mSvActivitySetkeyLoading;
    @BindView(R.id.pv_activity_setkey_time)
    PrintView mPvActivitySetkeyTime;
    @BindView(R.id.btn_activity_setkey_open)
    Button mBtnActivitySetkeyOpen;
    @BindView(R.id.btn_activity_setkey_again)
    Button mBtnActivitySetkeyAgain;
    private ObjectAnimator mObjectAnimator;
    private Subscription mSubscription;
    private Thread mThread;
    private ReaderPortThread mReaderPortThread;
    private boolean mResult = false;
    private SetKeyAdapter mSetKeyAdapter;
    private static KeyHolderService mKeyHolderService;
    private int errorCount = 0;
    private int keyId;
    private int keyType;
    private String keyVersion;
    private String serialNumber;
    private String keyTime;
    private int keyPos = -1;
    private String tagId = "";
    private KeyDataDao mKeyDataDao = new KeyDataImp();
    private KeyBasicInfo mKeyBasicInfo;
    private UserKeyInfo mUserKeyInfo;
    private HashMap<Integer, KeyData> mHashMap = new HashMap<>(4);
    private Handler mHandler = new Handler();
    private byte address;
    private int keyBoxId;
    private Subscription mSubscription1;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 0:
                    Toast.makeText(SetKeyActivity.this, R.string.noper, Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };
    private ServiceConnection mKeyHolderConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mKeyHolderService = ((KeyHolderService.LocalBinder) service).getService();
            byte[] key = {};
            mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.READ_KEY_LOCKED_COUNT, key));
            send(SetKeyActivity.this, START);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mKeyHolderService = null;
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_setkey);
        ButterKnife.bind(this);
        initData();

    }

    @Override
    protected void onPause() {
        super.onPause();
        unbindService(mKeyHolderConnection);
        unregisterReceiver(mKeyHolderReceiver);
        unregisterReceiver(mReceiver);
    }

    private BroadcastReceiver mKeyHolderReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            StringBuilder sb = new StringBuilder(64);
            final String action = intent.getAction();
            if (intent.getSerializableExtra(KeyHolderService.EXTRA_DATA) instanceof Integer) {
                return;
            }
            final KeyHolderData keyHolderData = (KeyHolderData) intent.getSerializableExtra(KeyHolderService.EXTRA_DATA);
            switch (action) {
                case KeyHolderService.ACTION_DATA_WRITE:
                    sb.append("SetKeySend:");
                    sb.append(HexUtil.encodeHexStr(keyHolderData.getData()));
                    Log.e("write", sb.toString());
                    break;
                case KeyHolderService.ACTION_DATA_READ:
                    sb.append("SetKeyRead:");
                    sb.append(String.format("%02X", keyHolderData.getCmd()) + "-");
                    sb.append(HexUtil.encodeHexStr(keyHolderData.getData()));

                    if (keyHolderData.getCmd() == (byte) 0x0b) {
                        if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01")) {
                            if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("00", 12)) {
                                mStatus.setDoorstatus(DOOR_CLOSE);
                            } else if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01", 12)) {
                                mStatus.setDoorstatus(DOOR_OPEN);
                            }
                        }

                    }
                    if (keyHolderData.getCmd() == KeyHolderCmd.RELEASE_KEYS) {
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                               send(SetKeyActivity.this, START);
                            }
                        }, 5 * 100);
                        if (HexUtil.encodeHexStr(keyHolderData.getData()).equals("01")) {
                            if (keyPos != -1 && keyPos != 0) {
                                Toast.makeText(SetKeyActivity.this, getString(R.string.get_update_key) + "(" + getString(R.string.key) + keyPos + "" + ")", Toast.LENGTH_SHORT).show();
                                doListen();
                            } else if (keyPos == 0) {
                                Toast.makeText(SetKeyActivity.this, getString(R.string.return_key_and_close_door), Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(SetKeyActivity.this, getString(R.string.open_door_successful), Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(SetKeyActivity.this, getString(R.string.open_door_failed), Toast.LENGTH_SHORT).show();

                        }
                    } else if (keyHolderData.getCmd() == KeyHolderCmd.READ_KEY_TAG_ID) {
                        if (HexUtil.encodeHexStr(keyHolderData.getData()).substring(0, 2).equals("01")) {
                            tagId = HexUtil.encodeHexStr(keyHolderData.getData()).substring(4, 12);
                            Log.e("tagid", tagId);
                            if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01", 2)) {
                                if (!tagId.equals("00000000")) {
                                    KeyData keyData = mKeyDataDao.getKeyDataByTagId(tagId);
                                    if (keyData != null) {
                                        keyData.setAddress(1);
                                        mKeyDataDao.updateKeyData(keyData);
                                    } else {
                                        keyData = new KeyData();
                                        keyData.setTagid(tagId);
                                        keyData.setKeybox(keyBoxId);
                                        keyData.setState(0);
                                        keyData.setAddress(1);
                                    }
                                    mHashMap.put(1, keyData);
//                                } else {
//                                    KeyData keyData = null;
//                                    mHashMap.put(1, keyData);
                                }
                            } else if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("02", 2)) {
                                if (!tagId.equals("00000000")) {
                                    KeyData keyData = mKeyDataDao.getKeyDataByTagId(tagId);
                                    if (keyData != null) {

                                        keyData.setAddress(2);
                                        mKeyDataDao.updateKeyData(keyData);
                                    } else {
                                        keyData = new KeyData();
                                        keyData.setTagid(tagId);
                                        keyData.setKeybox(keyBoxId);
                                        keyData.setState(0);
                                        keyData.setAddress(2);
                                    }
                                    mHashMap.put(2, keyData);
//                                } else {
//                                    KeyData keyData = null;
//                                    mHashMap.put(2, keyData);
                                }
                            } else if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("03", 2)) {
                                if (!tagId.equals("00000000")) {
                                    KeyData keyData = mKeyDataDao.getKeyDataByTagId(tagId);
                                    if (keyData != null) {
                                        keyData.setAddress(3);
                                        mKeyDataDao.updateKeyData(keyData);
                                    } else {
                                        keyData = new KeyData();
                                        keyData.setTagid(tagId);
                                        keyData.setKeybox(keyBoxId);
                                        keyData.setState(0);
                                        keyData.setAddress(3);
                                    }
                                    mHashMap.put(3, keyData);
//                                } else {
//                                    KeyData keyData = null;
//                                    mHashMap.put(3, keyData);
                                }
                            } else if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("04", 2)) {
                                if (!tagId.equals("00000000")) {
                                    KeyData keyData = mKeyDataDao.getKeyDataByTagId(tagId);
                                    if (keyData != null) {
                                        keyData.setAddress(4);
                                        mKeyDataDao.updateKeyData(keyData);
                                    } else {
                                        keyData = new KeyData();
                                        keyData.setTagid(tagId);
                                        keyData.setKeybox(keyBoxId);
                                        keyData.setState(0);
                                        keyData.setAddress(4);
                                    }
                                    mHashMap.put(4, keyData);
//                                } else {
//                                    KeyData keyData = null;
//                                    mHashMap.put(4, keyData);
                                }
                            }
                            mSetKeyAdapter.notifyDataSetChanged();
                        } else {
                            Toast.makeText(SetKeyActivity.this, getString(R.string.read_tag_failed), Toast.LENGTH_SHORT).show();
                        }
                    } else if (keyHolderData.getCmd() == KeyHolderCmd.READ_KEY_LOCKED_COUNT) {
                        mSvActivitySetkeyLoading.setVisibility(View.GONE);
                        if (HexUtil.encodeHexStr(keyHolderData.getData()).substring(0, 2).equals("01")) {
                            mHashMap.clear();
                            if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01", 4)) {
//                                KeyData keyData = mRealm.where(KeyData.class).equalTo("id", 1).findFirst();
//                                if (keyData != null) {
//                                } else {
//                                    keyData = new KeyData();
//                                    keyData.setId(1);
//                                    keyData.setState(0);
//                                }
//                                mList.add(keyData);
                                byte[] tag = {(byte) 0x01};
                                mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.READ_KEY_TAG_ID, tag));
                            } else {
                                KeyData keyData = null;
                                mHashMap.put(1, keyData);
                            }
                            if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01", 6)) {
//                                KeyData keyData = mRealm.where(KeyData.class).equalTo("id", 2).findFirst();
//                                if (keyData != null) {
//
//                                } else {
//                                    keyData = new KeyData();
//                                    keyData.setId(2);
//                                    keyData.setState(0);
//                                }
//                                mList.add(keyData);
                                byte[] tag = {(byte) 0x02};
                                mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.READ_KEY_TAG_ID, tag));
                            } else {
                                KeyData keyData = null;
                                mHashMap.put(2, keyData);
                            }
                            if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01", 8)) {
//
//                                KeyData keyData = mRealm.where(KeyData.class).equalTo("id", 3).findFirst();
//                                if (keyData != null) {
//
//                                } else {
//                                    keyData = new KeyData();
//                                    keyData.setId(3);
//                                    keyData.setState(0);
//                                }
//                                mList.add(keyData);
                                byte[] tag = {(byte) 0x03};
                                mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.READ_KEY_TAG_ID, tag));
                            } else {
                                KeyData keyData = null;
                                mHashMap.put(3, keyData);
                            }
                            if (HexUtil.encodeHexStr(keyHolderData.getData()).startsWith("01", 10)) {
//                                KeyData keyData = mRealm.where(KeyData.class).equalTo("id", 4).findFirst();
//                                if (keyData != null) {
//
//                                } else {
//                                    keyData = new KeyData();
//                                    keyData.setId(4);
//                                    keyData.setState(0);
//                                }
//                                mList.add(keyData);
                                byte[] tag = {(byte) 0x04};
                                mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.READ_KEY_TAG_ID, tag));
                            } else {
                                KeyData keyData = null;
                                mHashMap.put(4, keyData);
                            }
                        } else {
                            Toast.makeText(SetKeyActivity.this, getString(R.string.read_key_count_failed), Toast.LENGTH_SHORT).show();
                        }
                    }
                    Log.e("read", sb.toString());
                    break;
                case KeyHolderService.ACTION_CLOSE:
                    break;
                default:
                    break;
            }
        }
    };

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (!action.equals("setkey")) {
                return;
            }
            int value = intent.getIntExtra("flag", -1);
            if (value == START) {
                mSubscription1 = Observable.create(new Observable.OnSubscribe<String>() {
                    @Override
                    public void call(Subscriber<? super String> subscriber) {


                        subscriber.onNext("");
                        subscriber.onCompleted();
                        SystemClock.sleep(3000);

                    }
                }).repeat().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("time", e.toString());
                    }

                    @Override
                    public void onNext(String s) {

                        byte[] key = {};
                        mKeyHolderService.sendData(new KeyHolderData(address,(byte)0x0b, key));

//                    KeyHolderData device = new KeyHolderData(KeyHolderCmd.DEVICE_STATUS, key);
//                    KeyHolderData read = new KeyHolderData(KeyHolderCmd.READ_KEY_LOCKED_COUNT, key);
//                    mKeyHolderService.sendData(device);
//                    mKeyHolderService.sendData(read);
                    }
                });
            } else if (value == STOP) {
                CancelUtils.unsubscribe(mSubscription1);
            }
        }
    };
    private void initData() {
        BroadcastUtils.send(SetKeyActivity.this, STOP);
        keyBoxId = getIntent().getIntExtra("keyboxid",0);
        address = (byte) getIntent().getIntExtra("keyboxid",0);
        mSetKeyAdapter = new SetKeyAdapter(mHashMap, this);
        mRlvActivitySetkey.setLayoutManager(new GridLayoutManager(this, 2));
        mRlvActivitySetkey.setAdapter(mSetKeyAdapter);
        Intent service = new Intent(this, KeyHolderService.class);
        bindService(service, mKeyHolderConnection, Context.BIND_AUTO_CREATE);
        registerReceiver(mKeyHolderReceiver, makeUpdateIntentFilter());
        registerReceiver(mReceiver, intentFilter());
        mSvActivitySetkeyLoading.setIndeterminateDrawable(new Wave());
        mSvActivitySetkeyLoading.setVisibility(View.VISIBLE);
        mSetKeyAdapter.setOnClicker(new OnClicker() {
            @Override
            public void click(View v, int pos) {

            }

            @Override
            public void onClick(View v, final int pos,KeyData keyData) {
                KeyDataDao keyDataDao = new KeyDataImp();
                keyDataDao.delete(keyData);
                mHashMap.remove(keyData);
                mSetKeyAdapter.notifyDataSetChanged();
                keyPos = pos + 1;
                byte[] tag = {(byte) keyPos};
                mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.READ_KEY_TAG_ID, tag));
                send(SetKeyActivity.this, STOP);
                CancelUtils.unsubscribe(mSubscription);
                mSubscription = Observable.create(new Observable.OnSubscribe<String>() {
                    @Override
                    public void call(Subscriber<? super String> subscriber) {
                        subscriber.onNext(getString(R.string.ic_three));
                        SystemClock.sleep(1000);
                        subscriber.onNext(getString(R.string.ic_two));
                        SystemClock.sleep(1000);
                        subscriber.onNext(getString(R.string.ic_one));
                        SystemClock.sleep(1000);
                        subscriber.onCompleted();

                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        mPvActivitySetkeyTime.setVisibility(View.GONE);
                        byte[] rekey = getArray(keyPos);
                        mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.RELEASE_KEYS, rekey));
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        byte[] key = inttoTwoBytes(50);
                        mKeyHolderService.sendData(new KeyHolderData(address,(byte) 0x0c, key));
                        mPvActivitySetkeyTime.setIconText(s);
                        startAni();
                        mPvActivitySetkeyTime.setVisibility(View.VISIBLE);
                    }
                });
            }


            @Override
            public void longClick(View v, int pos) {
//                mSetKeyAdapter.setLongClickPos(pos);
//                mSetKeyAdapter.notifyDataSetChanged();
            }
        });
    }
    private IntentFilter intentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("setkey");
        return intentFilter;
    }
    private void startAni() {
        if (mObjectAnimator == null) {
            mObjectAnimator = ObjectAnimator.ofFloat(mPvActivitySetkeyTime, "alpha", 1f, 0f);
            mObjectAnimator.setDuration(1000);
        }
        mObjectAnimator.start();
    }

    private void clearAni() {
        if (mObjectAnimator != null && mObjectAnimator.isRunning()) {
            mObjectAnimator.cancel();
        }
    }

    @OnClick({R.id.btn_activity_setkey_bind, R.id.btn_activity_setkey_finish, R.id.btn_activity_setkey_open, R.id.btn_activity_setkey_again})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_activity_setkey_bind:
                bind();
                break;
            case R.id.btn_activity_setkey_finish:
                setResult(RESULT_OK);
                finish();
                break;
            case R.id.btn_activity_setkey_open:
                setUnClick();
                CancelUtils.unsubscribe(mSubscription);
                keyPos = 0;
                BroadcastUtils.send(SetKeyActivity.this, STOP);
                mSubscription = Observable.create(new Observable.OnSubscribe<String>() {
                    @Override
                    public void call(Subscriber<? super String> subscriber) {
                        subscriber.onNext(getString(R.string.ic_three));
                        SystemClock.sleep(1000);
                        subscriber.onNext(getString(R.string.ic_two));
                        SystemClock.sleep(1000);
                        subscriber.onNext(getString(R.string.ic_one));
                        SystemClock.sleep(1000);
                        subscriber.onCompleted();

                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        mPvActivitySetkeyTime.setVisibility(View.GONE);
                        byte[] rekey = new byte[4];
                        mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.RELEASE_KEYS, rekey));
                        setClick();
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        byte[] key = TimeFormatUtil.inttoTwoBytes(50);
                        mKeyHolderService.sendData(new KeyHolderData(address,(byte) 0x0c, key));
                        mPvActivitySetkeyTime.setIconText(s);
                        startAni();
                        mPvActivitySetkeyTime.setVisibility(View.VISIBLE);
                    }
                });
                break;
            case R.id.btn_activity_setkey_again:
                mBtnActivitySetkeyAgain.setVisibility(View.GONE);
                errorCount = 0;
                doListen();
                break;
        }
    }

    private void doListen() {
        List<PortClass> port = new ArrayList<>();
        PortClass portClass = new PortClass(ReaderPort.DETIVER_2,true,true,false);
        port.add(portClass);

        stop();
        mReaderPortThread = new ReaderPortThread(port) {
            @Override
            protected void onSendNfcKeyReader(String s, int i) {
                if (mStatus.getDoorstatus() == DOOR_CLOSE) {
                    mKeyBasicInfo = new KeyBasicInfo();
                    mKeyBasicInfo.setKeyType(KeyBasicInfo.NFC_KEY);


                    byte[] code = new byte[16];
                    byte[] sys_Code = HexUtil.decodeHex(GlobalVariables.getInstance().getmSiteData().getSyscode().toCharArray());
                    if (null != sys_Code && 8 == sys_Code.length) {
                        int ret = WallreaderJni.getmInstance().des(1, sys_Code, sys_Code.length, code);
                        if (ret > 0) {

                            System.arraycopy(code, 0, mKeyBasicInfo.getSysCode(), 0, 4);
//                        System.arraycopy(code, 0, keyBasicInfo.getSysCode(), 0, 4);
//                        System.arraycopy(code, 0,  this.cardBasicInfo.getSysCode(), 0, 4);
                        }
                    }
                    byte[] reg_Code = HexUtil.decodeHex(GlobalVariables.getInstance().getmSiteData().getRegcode().toCharArray());
                    if (null != reg_Code && 8 == reg_Code.length) {
                        int ret = WallreaderJni.getmInstance().des(1, reg_Code, reg_Code.length, code);
                        if (ret > 0) {
                            System.arraycopy(code, 0, mKeyBasicInfo.getRegCode(), 0, 4);
//                        System.arraycopy(code, 0, keyBasicInfo.getRegCode(), 0, 4);
//                        System.arraycopy(code, 0, this.cardBasicInfo.getRegCode(), 0, 4);
                        }
                    }
                    writeToKey(mReaderPortThread, mKeyBasicInfo);
                    this.stop();
                    if (!mResult) {
                        errorCount++;
                        if (errorCount == 3) {
                            SetKeyActivity.this.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mBtnActivitySetkeyAgain.setVisibility(View.VISIBLE);
                                    Toast.makeText(SetKeyActivity.this, R.string.bind_failed, Toast.LENGTH_SHORT).show();

                                }
                            });
                        } else if (errorCount < 3) {
                            doListen();
                        }
                    } else {
                        if (mHashMap.get(keyPos) != null) {
                            KeyData m = null;
                            KeyData data = mHashMap.get(keyPos);
                            data.setType(keyType);
                            data.setState(1);
                            data.setVersion(keyVersion);
                            data.setSerialnumber(serialNumber);
                            data.setTime(new Date());
                            data.setAddress(keyPos);
                            m = mKeyDataDao.getKeyDataBySerialnumber(serialNumber);
                            if (m != null) {
                                mKeyDataDao.delete(m);
                            }
                            mKeyDataDao.addKeyData(data);

                        }
                        SetKeyActivity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (mHashMap.get(keyPos) != null) {
                                    mSetKeyAdapter.notifyDataSetChanged();
                                }
                                ToastUtils.showShortToast(SetKeyActivity.this,getString( R.string.bind_successful));

                            }
                        });
                    }
                } else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ToastUtils.showShortToast(SetKeyActivity.this, getString(R.string.must_close_door));
                        }
                    });

                }
            }

            @Override
            protected void onSendBleKeyReader(String s, int i) {
                SiteDao siteDao = new SiteImpl();
                SiteData siteData = siteDao.findFirst();
                if (siteData==null){
                    handler.sendEmptyMessage(0);
                    return;
                }
                if (!siteData.getSupportkey().contains("BLE")){
                    handler.sendEmptyMessage(0);
                    return;
                }
                if (mStatus.getDoorstatus() == DOOR_CLOSE) {
                    mKeyBasicInfo = new KeyBasicInfo();
                    mKeyBasicInfo.setKeyType(KeyBasicInfo.BLE_KEY);
                    byte[] code = new byte[16];
                    byte[] sys_Code = HexUtil.decodeHex(GlobalVariables.getInstance().getmSiteData().getSyscode().toCharArray());
                    if (null != sys_Code && 8 == sys_Code.length) {
                        int ret = WallreaderJni.getmInstance().des(1, sys_Code, sys_Code.length, code);
                        if (ret > 0) {

                            System.arraycopy(code, 0, mKeyBasicInfo.getSysCode(), 0, 4);
//                        System.arraycopy(code, 0, keyBasicInfo.getSysCode(), 0, 4);
//                        System.arraycopy(code, 0,  this.cardBasicInfo.getSysCode(), 0, 4);
                        }
                    }
                    byte[] reg_Code = HexUtil.decodeHex(GlobalVariables.getInstance().getmSiteData().getRegcode().toCharArray());
                    if (null != reg_Code && 8 == reg_Code.length) {
                        int ret = WallreaderJni.getmInstance().des(1, reg_Code, reg_Code.length, code);
                        if (ret > 0) {
                            System.arraycopy(code, 0, mKeyBasicInfo.getRegCode(), 0, 4);
//                        System.arraycopy(code, 0, keyBasicInfo.getRegCode(), 0, 4);
//                        System.arraycopy(code, 0, this.cardBasicInfo.getRegCode(), 0, 4);
                        }
                    }
                    writeToKey(mReaderPortThread, mKeyBasicInfo);
                    this.stop();
                    if (!mResult) {
                        errorCount++;
                        if (errorCount == 3) {
                            SetKeyActivity.this.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mBtnActivitySetkeyAgain.setVisibility(View.VISIBLE);
                                    Toast.makeText(SetKeyActivity.this, R.string.bind_failed, Toast.LENGTH_SHORT).show();

                                }
                            });
                        } else if (errorCount < 3) {
                            doListen();
                        }
                    } else {
                        if (mHashMap.get(keyPos) != null) {
                            KeyData m = null;
                            KeyData data = mHashMap.get(keyPos);
                            data.setType(keyType);
                            data.setState(1);
                            data.setVersion(keyVersion);
                            data.setSerialnumber(serialNumber);
                            data.setTime(new Date());
                            data.setAddress(keyPos);
                            m = mKeyDataDao.getKeyDataBySerialnumber(serialNumber);
                            if (m != null) {
                                mKeyDataDao.delete(m);
                            }
                            mKeyDataDao.addKeyData(data);

                        }
                        SetKeyActivity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (mHashMap.get(keyPos) != null) {
                                    mSetKeyAdapter.notifyDataSetChanged();
                                }
                                Toast.makeText(SetKeyActivity.this, R.string.bind_successful, Toast.LENGTH_SHORT).show();

                            }
                        });
                    }
                } else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ToastUtils.showShortToast(SetKeyActivity.this, getString(R.string.must_close_door));
                        }
                    });
                }
            }

            @Override
            protected void onSendCardReader(String s, int i, byte[] bytes) {

            }

            @Override
            protected void onNoReader(String s, int i) {

            }

            @Override
            protected void onPlugInRelay(String s, int i) {

            }

            @Override
            protected void onStopReader() {

            }

        };
        mThread = new Thread(mReaderPortThread);
        mThread.start();
    }

    private void stop() {
        if (mReaderPortThread != null && !mReaderPortThread.isStop) {
            mReaderPortThread.stop();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stop();
        mThread = null;
        clearAni();
        BroadcastUtils.send(SetKeyActivity.this, START);
        send(SetKeyActivity.this, STOP);
        mHandler.removeCallbacksAndMessages(null);
        CancelUtils.unsubscribe(mSubscription);
        CancelUtils.unsubscribe(mSubscription1);
    }

    public static void send(Context context,int flag){
        Intent intent=new Intent();
        intent.setAction("setkey");
        intent.putExtra("flag",flag);
        context.sendBroadcast(intent);
    }
    private void writeToKey(ReaderPortThread mReaderPortThread, KeyBasicInfo keyBasicInfo) {
        if (connectKey(mReaderPortThread, keyBasicInfo)) {


            SiteDao siteDao = new SiteImpl();
            SiteData siteData = siteDao.findFirst();
            if (siteData.getSupportkey()==null){
                handler.sendEmptyMessage(0);
                mResult=false;
                this.stop();
                return;
            }
            if (keyVersion.contains("RCLB")){
                if (!siteData.getSupportkey().substring(0,3).equals("NFC")){
                    handler.sendEmptyMessage(0);
                    mResult=false;
                    this.stop();
                    return;
                }
            }else if (keyVersion.contains("B03014")){
                if (!siteData.getSupportkey().contains("MiniNFC")){
                    handler.sendEmptyMessage(0);
                    mResult=false;
                    this.stop();
                    return;
                }
            }
            if (mKeyBasicInfo.getKeyType() == KeyBasicInfo.BLE_KEY) {

            } else {
                keyBasicInfo.setRegCode(HexUtil.decodeHex(AppUtils.getDecode(GlobalVariables.getInstance().getmSiteData().getRegcode()).toCharArray()));
                keyBasicInfo.setSysCode(HexUtil.decodeHex(AppUtils.getDecode(GlobalVariables.getInstance().getmSiteData().getSyscode()).toCharArray()));
                writeUserKey(mReaderPortThread, keyBasicInfo, newUserKey());
            }

        }

    }

    private boolean connectKey(final ReaderPortThread mReaderPortThread, final KeyBasicInfo pKeyBasicInfo) {

        mReaderPortThread.getmPortReadBiz().findKey(pKeyBasicInfo, new OnPortListener.OnFindListener() {
            @Override
            public void findSuccess() {

                mResult = true;
                keyId = pKeyBasicInfo.getKeyId();
                keyType = pKeyBasicInfo.getType();
                keyVersion = pKeyBasicInfo.getVersion();


                serialNumber = HexUtil.encodeHexStr(pKeyBasicInfo.getSerial());
                KeyDataDao keyDataDao = new KeyDataImp();
                KeyData keyData = keyDataDao.getKeyDataBySerialnumber(serialNumber);
                if (keyData!=null&&keyData.getState()==1){
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(SetKeyActivity.this, R.string.auth_failed_err, Toast.LENGTH_SHORT).show();
                        }
                    });
                    return ;
                }

                keyTime = TimeFormatUtil.localDateTimeFormat(TimeUtils.dateFromNotYMDWHMS(
                        HexUtil.encodeHexStr(pKeyBasicInfo.getKeyTime())).getTime());
                String txt = "Find key successfully \n";
                txt += "Key Id: " + pKeyBasicInfo.getKeyId() + "\n";
                txt += "Key Type: "
                        + String.format("%2X", pKeyBasicInfo.getType())
                        + "\n";
                txt += "Key Group Id: " + pKeyBasicInfo.getGroupId()
                        + "\n";
                txt += "Key Version: " + pKeyBasicInfo.getVersion()
                        + "\n";
                txt += "Key Serial Number: "
                        + HexUtil.encodeHexStr(pKeyBasicInfo
                        .getSerial()) + "\n";
                txt += "Key Time: "
                        + TimeFormatUtil.localDateTimeFormat(TimeUtils
                        .dateFromNotYMDWHMS(
                                HexUtil.encodeHexStr(pKeyBasicInfo
                                        .getKeyTime()))
                        .getTime()) + "\n";
                Log.e("txt", txt);

            }

            @Override
            public void findFailed() {
                mResult = false;
                byte reg[] = {49,49,49,49};
                byte sys[] = {54,54,54,54};
                mKeyBasicInfo.setRegCode(reg);
                mKeyBasicInfo.setSysCode(sys);
                writeToKey(mReaderPortThread, mKeyBasicInfo);
            }
        });
        return mResult;
    }

    private IntentFilter makeUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(KeyHolderService.ACTION_DATA_READ);
        intentFilter.addAction(KeyHolderService.ACTION_DATA_WRITE);
        intentFilter.addAction(KeyHolderService.ACTION_CLOSE);
        return intentFilter;
    }

    private void writeUserKey(final ReaderPortThread mReaderPortThread,
                              KeyBasicInfo pKeyBasicInfo, UserKeyInfo pUserKeyInfo) {

        mReaderPortThread.getmPortReadBiz().writeUserKey(pKeyBasicInfo, pUserKeyInfo, new OnPortListener.OnWriteKeyListener() {
            @Override
            public void writeKeySuccess() {
                Log.e("write", "Write user key successfully");
                mResult = true;

            }

            @Override
            public void writeKeyFailed() {
                Log.e("write", "Write user key failed");
                mResult = false;
            }
        });


    }

    private void bind() {
        setUnClick();
        keyPos = -1;
        for (int i = 0; i < 4; i++) {
            if (mHashMap.get((i + 1)) != null && mHashMap.get((i + 1)).getState() == 0) {
                keyPos = (i + 1);
                break;
            }
        }
        if (keyPos != -1) {
            send(SetKeyActivity.this, STOP);
            CancelUtils.unsubscribe(mSubscription);
            mSubscription = Observable.create(new Observable.OnSubscribe<String>() {
                @Override
                public void call(Subscriber<? super String> subscriber) {
                    subscriber.onNext(getString(R.string.ic_three));
                    SystemClock.sleep(1000);
                    subscriber.onNext(getString(R.string.ic_two));
                    SystemClock.sleep(1000);
                    subscriber.onNext(getString(R.string.ic_one));
                    SystemClock.sleep(1000);
                    subscriber.onCompleted();

                }
            }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
                @Override
                public void onCompleted() {
                    mPvActivitySetkeyTime.setVisibility(View.GONE);
                    byte[] rekey = getArray(keyPos);
                    mKeyHolderService.sendData(new KeyHolderData(address,KeyHolderCmd.RELEASE_KEYS, rekey));
                    setClick();
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(String s) {
                    byte[] key = TimeFormatUtil.inttoTwoBytes(50);
                    mKeyHolderService.sendData(new KeyHolderData(address,(byte) 0x0c, key));
                    mPvActivitySetkeyTime.setIconText(s);
                    startAni();
                    mPvActivitySetkeyTime.setVisibility(View.VISIBLE);
                }
            });
        } else {
            Toast.makeText(this, getString(R.string.all_keys_are_binded), Toast.LENGTH_SHORT).show();
            setClick();
        }
    }

    private void setUnClick() {
        mBtnActivitySetkeyOpen.setClickable(false);
        mBtnActivitySetkeyBind.setClickable(false);
    }

    private void setClick() {
        mBtnActivitySetkeyOpen.setClickable(true);
        mBtnActivitySetkeyBind.setClickable(true);
    }

    private byte[] getArray(int pos) {
        byte[] ret = new byte[4];
        if (pos == 1) {
            ret[0] = 0x01;
            ret[1] = 0x00;
            ret[2] = 0x00;
            ret[3] = 0x00;
        } else if (pos == 2) {
            ret[0] = 0x00;
            ret[1] = 0x01;
            ret[2] = 0x00;
            ret[3] = 0x00;
        } else if (pos == 3) {
            ret[0] = 0x00;
            ret[1] = 0x00;
            ret[2] = 0x01;
            ret[3] = 0x00;
        } else if (pos == 4) {
            ret[0] = 0x00;
            ret[1] = 0x00;
            ret[2] = 0x00;
            ret[3] = 0x01;
        }
        return ret;
    }

    private UserKeyInfo newUserKey() {
        Calendar nowtime = Calendar.getInstance();

        mKeyBasicInfo.setKeyId(1);
        mKeyBasicInfo.setType(KeyType.USER_KEY.toByte());

        Calendar calendar = Calendar.getInstance();
        mKeyBasicInfo.setKeyTime(TimeUtils.calToBytesYMDWHMS(calendar));
        mKeyBasicInfo.setKeyIssueTime(TimeUtils.dateToBytesYMDHM(calendar.getTime()));
        mKeyBasicInfo.setBeginTime(TimeUtils.dateToBytesYMDHM(nowtime.getTime()));
        nowtime.add(Calendar.HOUR_OF_DAY, 2);
        mKeyBasicInfo.setEndTime(TimeUtils.dateToBytesYMDHM(nowtime.getTime()));
        mKeyBasicInfo.setVerifyDay(0);
        mUserKeyInfo = new UserKeyInfo();

//        // Calendar
        List<UserKeyInfo.CalendarInfo> CalList = new ArrayList<>();
        for (int cal = 0; cal < 30; cal++) {
            UserKeyInfo.CalendarInfo calday = new UserKeyInfo.CalendarInfo();
            calday.CalDate = Calendar.getInstance();
            calday.CalDate.add(Calendar.DATE, cal + 10);
            calday.Type = cal % 4;
            CalList.add(calday);
        }
        mUserKeyInfo.setCalendarInfo(CalList);
//
        // DaylightSaving
        UserKeyInfo.DSTInfo dst = new UserKeyInfo.DSTInfo();
        dst.BeginDate = Calendar.getInstance();
        dst.EndDate = Calendar.getInstance();
        dst.EndDate.add(Calendar.MONTH, 6);
        mUserKeyInfo.setDST(dst);

//         Timezone
//         Timezone MAX：200；Time MAX：12
        List<UserKeyInfo.TimezoneInfo> timeList = new ArrayList<UserKeyInfo.TimezoneInfo>();
        List<UserKeyInfo.ZoneInfo> zoneList = new ArrayList<UserKeyInfo.ZoneInfo>();
        for (int z = 0; z < 3; z++) {
            for (int t = 0; t < 12; t++) {
                UserKeyInfo.TimezoneInfo time = new UserKeyInfo.TimezoneInfo();
                Date date = new Date(13, 5, 00, 00, 00);
                time.ZoneNo = z + 1;
                time.TimeNo = t + 1;
                time.From.setTime(date);
                date = new Date(14, 8, 19, 23, 59);
                time.To.setTime(date);
                time.Su = false;
                time.Mo = false;
                time.Tu = false;
                time.We = false;
                time.Th = false;
                time.Fr = false;
                time.Sa = false;
                time.Hol = false;
                time.Sp1 = false;
                time.Sp2 = false;
                timeList.add(time);
            }
            UserKeyInfo.ZoneInfo zone = new UserKeyInfo.ZoneInfo();
            zone.ZoneNo = z + 1;
            zone.TimeCount = 12;
            zoneList.add(zone);
        }
        mUserKeyInfo.setTimezoneInfo(timeList);
        mUserKeyInfo.setZoneInfo(zoneList);
        mUserKeyInfo.setTimezoneCount(zoneList.size());

        //add edit open permission
        List<UserKeyInfo.Open> openList = new ArrayList<UserKeyInfo.Open>();
        for (int open = 0; open < 20; open++) {
            UserKeyInfo.Open opens = new UserKeyInfo.Open(UserKeyInfo.Open.LOCK_TYPE, open + 1, 1);
            openList.add(opens);
        }
        mUserKeyInfo.setOpens(openList);
//                 TempOpens MAX：100
        List<UserKeyInfo.TempOpen> tempList = new ArrayList<UserKeyInfo.TempOpen>();
        for (int temp = 0; temp < 10; temp++) {
            UserKeyInfo.TempOpen topen = new UserKeyInfo.TempOpen();
            topen.EndDate.add(Calendar.MONTH, 2);
            topen.FromTime.set(Calendar.HOUR_OF_DAY, 8);
            topen.FromTime.set(Calendar.MINUTE, 30);
            topen.ToTime.set(Calendar.HOUR_OF_DAY, 22);
            topen.ToTime.set(Calendar.MINUTE, 30);
            topen.LockId = temp + 1;
            tempList.add(topen);
        }
        mUserKeyInfo.setTempOpens(tempList);
        return mUserKeyInfo;
    }
}

